#ifndef Matrix4H
#define Matrix4H

#include"Vector4.h"
#include<iostream>


// Matrix4
class Matrix4
{
public:

	static const unsigned int ROWCOUNT     = 4;
	static const unsigned int COLUMNCOUNT  = 4;
	static const unsigned int ELEMENTCOUNT = ROWCOUNT * COLUMNCOUNT;
	static const float        EQUALLIMIT;
	static const Matrix4      ZERO;
	static const Matrix4      IDENTITY;

	union
	{
		float mElement[ROWCOUNT][COLUMNCOUNT];
		float mElement2[ELEMENTCOUNT];
		struct
		{
			float m00, m01, m02, m03,
				  m10, m11, m12, m13,
				  m20, m21, m22, m23,
				  m30, m31, m32, m33;
		};
	};

	 Matrix4();
	 Matrix4( const Matrix4& m );
	 Matrix4( float _00, float _01, float _02, float _03,
			  float _10, float _11, float _12, float _13,
			  float _20, float _21, float _22, float _23,
			  float _30, float _31, float _32, float _33 );
	 Matrix4( const float data[ELEMENTCOUNT] );
	 Matrix4( const int   data[ELEMENTCOUNT] );
	~Matrix4();

	const Matrix4& operator +  () const;
	Matrix4        operator -  () const;
	Matrix4        operator +  ( const Matrix4& m ) const;
	Matrix4        operator -  ( const Matrix4& m ) const;
	Matrix4        operator *  ( const Matrix4& m ) const;
	Matrix4        operator *  ( float s ) const;
	Matrix4        operator /  ( float s ) const;
	Matrix4&       operator =  ( const Matrix4& m );
	Matrix4&       operator += ( const Matrix4& m );
	Matrix4&       operator -= ( const Matrix4& m );
	Matrix4&       operator *= ( const Matrix4& m );
	Matrix4&       operator *= ( float s );
	Matrix4&       operator /= ( float s );
	bool           operator == ( const Matrix4& m ) const;
	bool           operator != ( const Matrix4& v ) const;

	Vector4 GetRowVector   ( unsigned int row    ) const;
	Vector4 GetColumnVector( unsigned int column ) const;

};


Matrix4 operator * ( float s, const Matrix4& m );
std::ostream& operator << ( std::ostream& o, const Matrix4& m );


#endif
